﻿using System;
using NHibernate.Event;

namespace Xenta.Events
{
    /// <summary>
    /// Represents an event which incapsulates the NHibernate 
    /// session generated event.
    /// </summary>
    /// <typeparam name="TEvent">The type of session generated event.</typeparam>
    public class NHibernateEvent<TEvent> : Event<IEventSource, TEvent>
        where TEvent : AbstractEvent
    {
        #region Ctors

        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <param name="evt">The incapsulated NHibernate event.</param>
        public NHibernateEvent(TEvent evt)
            : base(evt.Session, evt)
        {
        }

        #endregion
    }

    internal class NHibernateEventInterpreter : 
        IPreInsertEventListener, 
        IPostInsertEventListener, 
        IPreUpdateEventListener, 
        IPostUpdateEventListener, 
        IPreDeleteEventListener,
        IPostDeleteEventListener,
        IPostCollectionUpdateEventListener
    {
        #region Fields

        private IEventBroker _eventBroker;

        #endregion

        #region Methods

        public static NHibernateEventInterpreter Attach(EventListeners eventListners)
        {
            if(eventListners == null)
                throw new ArgumentNullException();

            var instance = new NHibernateEventInterpreter();

            eventListners.PreInsertEventListeners = new IPreInsertEventListener[]
            {
                instance
            };
            eventListners.PostInsertEventListeners = new IPostInsertEventListener[]
            {
                instance
            };
            eventListners.PreUpdateEventListeners = new IPreUpdateEventListener[]
            {
                instance
            };
            eventListners.PostUpdateEventListeners = new IPostUpdateEventListener[]
            {
                instance
            };
            eventListners.PreDeleteEventListeners = new IPreDeleteEventListener[]
            {
                instance
            };
            eventListners.PostDeleteEventListeners = new IPostDeleteEventListener[]
            {
                instance
            };
            eventListners.PostCollectionUpdateEventListeners = new IPostCollectionUpdateEventListener[]
            {
                instance
            };

            return instance;
        }

        public void Attach(IEventBroker eventBroker)
        {
            _eventBroker = eventBroker;
        }

        public bool OnPreInsert(PreInsertEvent evt)
        {
            if(_eventBroker != null)
                _eventBroker.Publish(new NHibernateEvent<PreInsertEvent>(evt));
            return false;
        }

        public void OnPostInsert(PostInsertEvent evt)
        {
            if(_eventBroker != null)
                _eventBroker.Publish(new NHibernateEvent<PostInsertEvent>(evt));
        }

        public bool OnPreUpdate(PreUpdateEvent evt)
        {
            if(_eventBroker != null)
                _eventBroker.Publish(new NHibernateEvent<PreUpdateEvent>(evt));
            return false;
        }

        public void OnPostUpdate(PostUpdateEvent evt)
        {
            if(_eventBroker != null)
                _eventBroker.Publish(new NHibernateEvent<PostUpdateEvent>(evt));
        }

        public bool OnPreDelete(PreDeleteEvent evt)
        {
            if(_eventBroker != null)
                _eventBroker.Publish(new NHibernateEvent<PreDeleteEvent>(evt));
            return false;
        }

        public void OnPostDelete(PostDeleteEvent evt)
        {
            if(_eventBroker != null)
                _eventBroker.Publish(new NHibernateEvent<PostDeleteEvent>(evt));
        }

        public void OnPostUpdateCollection(PostCollectionUpdateEvent evt)
        {
            if(_eventBroker != null)
                _eventBroker.Publish(new NHibernateEvent<PostCollectionUpdateEvent>(evt));
        }

        #endregion
    }
}
